package com.xyzk.diagnose.tools;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.xyzk.diagnose.TApplication;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;


public class Commonfunc {
	private static SharedPreferences share = TApplication.getContext().getSharedPreferences("user", Context.MODE_PRIVATE);;
	/**
	 * 把字节数组转换成16进制字符串
	 * @param bArray 字节数组
	 * @return String 转换成的字符串AA 12 13
	 */
	public static  String bytesToHexStringSpace(byte[] bArray, int start, int end) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		int last = end - 1;
		for (int i = start; i < end; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2) sb.append("0");
			sb.append(sTemp.toUpperCase(Locale.CHINA));
			if (i != last) sb.append(" ");
		}
		return sb.toString();
	}

	/**
	 * 把字节数组转换成16进制字符串
	 * @param bArray 字节数组
	 * @return String 转换成的字符串AA1213
	 */
	public static String bytesToHexString(byte[] bArray, int start, int end) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = start; i < end; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2) sb.append("0");
			sb.append(sTemp.toUpperCase(Locale.CHINA));
		}
		return sb.toString();
	}

	/****
	 * @author 把字节数组转换成16进制字符串
	 * @param bArray
	 *            字节数组
	 * @return String 转换成的字符串
	 */
	public static final String Chery_kf_bytesToHexString(byte[] bArray, int start,int end) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		// int v_len = bArray.length;
		int last = end - 1;
		//sb.append("0x");
		for (int i = start; i < end; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append("0");
			sb.append(sTemp.toUpperCase());
			if (i != last)
				sb.append(" ");
		}
		return sb.toString();
	}
	public static boolean Bequals(byte[] a, byte[] a2) {
		if (a==a2)
			return true;
		if (a==null || a2==null)
			return false;

		int length = a.length;
		if (a2.length < length)
			length = a2.length;

		for (int i=0; i<length; i++)
			if (a[i] != a2[i])
				return false;

		return true;
	}
	public static boolean Bequals(byte[] a, byte[] a2,int a2Pos) {
		if (a==a2)
			return true;
		if (a==null || a2==null)
			return false;

		int length = a.length;
		if (a2.length < length)
			length = a2.length;

		for (int i=0; i<length; i++)
			if (a[i] != a2[a2Pos + i])
				return false;

		return true;
	}
	/**
	 * 把单个字节转换成16进制字符串
	 * @param bArray 字节
	 * @return String 转换成的字符串01
	 */
	public static  String byteToHexString(byte bt){
		String st = Integer.toHexString(0xFF & bt);
		if(st.length() < 2) st = "0" + st;
		return st.toUpperCase(Locale.CHINA);
	}

	/**
	 * 把单个字节转换成十进制字符串
	 * @param bArray 字节 10
	 * @return String 转换成的字符串10
	 */
	public static  String byteToString(byte bt){
		String st = Integer.toString(0xFF & bt);
		if(st.length() < 2) st = "0" + st;
		return st;
	}

	/**
	 * 把Integer整数转换成16进制字符串
	 * @param int
	 * @return String 转换成的字符串7DF
	 */
	public static String canidToHexString(int canid){
		String st = Integer.toHexString(canid).toUpperCase(Locale.CHINA);
		if(st.length() < 2){
			st = "00" + st;
		}else if(st.length() < 3){
			st = "0" + st;
		}
		return st;
	}

	/**
	 * 计算校验码
	 * @param data数组
	 * @param start起始位置
	 * @param end 结束位置
	 * @return 校验码byte
	 */
	public static byte calcuCheckCode(byte[] data, int start, int end) {
		byte chechsum = 0;
		if (start >= 0 && start < end && data != null && data.length > 0) {
			for (int i = start; i < end; i++) {
				chechsum += data[i];
			}
			return (byte) chechsum;
		}
		return 0;
	}


	/**
	 * 将16进制字符串转换成byte数组 20 30 AB
	 * @param cmdstr 16进制字符串 20 30 AB
	 * @param cmdlen 字节长度
	 */
	public static void cmdStringToBytes(String cmdstr, byte[] cmdbuf){
		for(int i = 0; i < cmdbuf.length; i ++){
			String data = cmdstr.substring(i * 3, i * 3 + 2);
			cmdbuf[i] = (byte) hexStringtoInt(data);
		}
	}
	public static final String bytesToHexStringP(byte[] bArray, int start,int end) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		int v_len = bArray.length;
		int last = end - 1;
		//sb.append("0x");
		for (int i = start; i < end; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append("0");
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}
	public static int CmdStringToBytes(String cmdstr,byte[] cmdbuf,int cmdlen)
	{
		//if(Common.Debug) Log.i(TAG,"Src:" + cmdstr);
		int strlen = cmdstr.length();
		for(int i = 0; i < cmdlen; i ++)
		{
			String data = "";
			if(strlen >= (i* 3 + 2))
				data = cmdstr.substring(i * 3, i * 3 + 2);
			//if(Common.Debug) Log.i(TAG,"data:"+ data);
			if(data != null)
				cmdbuf[i] = (byte) hexStringtoInt(data);
		}
		//if(Common.Debug) Log.i(TAG,"Obj:"+ bytesToHexString(cmdbuf, 0,cmdlen));
		return cmdlen;
	}


	/**
	 * 将16进制字符串转换成byte数组 2030AB
	 * @param str 16进制字符串 2030AB
	 * @param buf 字节长度
	 */
	public static void hexStringToBytes(String str, byte[] buf){
		for(int i = 0; i < buf.length; i ++){
			String data = str.substring(i * 2, i * 2 + 2);
			buf[i] = (byte) hexStringtoInt(data);
		}
	}

	/**
	 * 将单个16进制字符串转换成Integer
	 * @param hexStr 16进制间隔字节字符串 07
	 * @return Integer整形值
	 */
	public static int hexStringtoInt(String hexStr){
		int x = 0,iRet = 0;
		if(hexStr != null){
			for(int i = 0; i <hexStr.length(); i ++){
				x = charToHexInt(hexStr.charAt(i));
				iRet=(iRet<<4)|x;
			}
		}
		return iRet;
	}

	/**
	 * 将字符转换成Integer
	 * @param c 字节
	 * @return integer
	 */
	public static int charToHexInt(char c){
		int x = 0;
		if(c >= 'a' && c <= 'f'){
			x = c - 'a' + 10;
		}else if(c>= 'A' && c <= 'F'){
			x = c-'A'+10;
		}else if(c >= '0' && c <= '9'){
			x  =c-'0';
		}
		return x;
	}



	/**
	 * 将十进制字符串转换成byte数组 203040
	 * @param cmdstr 10进制字符串 203040
	 * @param cmdlen 字节长度
	 */
	public static void stringToBytes(String str, byte[] buf){
		for(int i = 0; i < buf.length; i ++){
			String data = str.substring(i * 2, i * 2 + 2);
			buf[i] = (byte) hexStringtoInt(data);
		}
	}

	/**
	 * 十六进制转BCD码
	 * @param code
	 * @return
	 */
	public static byte hexToBCD(byte code){
		return (byte) ((code / 10) * 0x10 + (code % 10));
	}

	/**
	 * 将Long类型数据转换成四个字节的byte数组
	 * @param num
	 * @return
	 */
	public static byte[] longTobytes(long num){
		byte[] b = new byte[4];
		b[0] = (byte) (num >> 24);
		b[1] = (byte) (num >> 16);
		b[2] = (byte) (num >> 8);
		b[3] = (byte) num;
		return b;
	}

	/**
	 * 校验VIN码格式
	 * @param vin VIN码字节
	 * @return boolean 是否符合VIN码规则
	 */
	public static boolean checkVinFormat(byte[] vin){
		if(vin.length != 17||vin[0] < 'A' || vin[0] > 'Z') return false;
		int [] jiaquan = {8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2};
		int slt = 0;
		for(int i = 0; i < 17; i ++){
			if(i == 8) continue;
			slt +=getVinFormat(vin[i]) * jiaquan[i];
		}
		int result = slt % 11;
		if(result == 10){
			if(vin[8] == 'X') return true;
		}else{
			if(vin[8] == (result + 0x30)) return true;
		}
		return false;
	}

	/**
	 * 校验获取字符对应值
	 */
	private static int getVinFormat(byte Pv){
		if(Pv >= '0' && Pv <= '9')
			return Pv - 0x30;
		else if(Pv >= 'A' && Pv <= 'H')
			return Pv - 'A' + 1;
		else if(Pv >= 'J' && Pv <= 'N')
			return Pv - 'J' + 1;
		else if(Pv == 'P')
			return 7;
		else if(Pv == 'R')
			return 9;
		else if(Pv >= 'S' && Pv <= 'Z')
			return Pv - 'S' + 2;
		else
			return -1;
	}

	/**
	 * 获取directory下面的子文件夹(不包含文件)
	 * @param path 文件路径
	 * @return 返回当前文件夹下所有子文件夹名称列表
	 */
	public static ArrayList<String> getDirectorySonList(String path){
		ArrayList<String> list = new ArrayList<String>();
		File file = new File(path);
		if(file != null&&file.isDirectory()){
			File [] files = file.listFiles();
			for(int i = 0; i < files.length; i ++){
				if(files[i].isDirectory())
					list.add(files[i].getName());
			}
		}
		return list;
	}

	/**
	 * 获取directory下面的子文件(包含文件、文件夹)
	 * @param path 文件路径
	 * @return 返回当前文件夹下所有子文件名称列表
	 */
	public static ArrayList<String> getFileSonList(String path){
		ArrayList<String> list = new ArrayList<String>();
		File file = new File(path);
		if(file != null&&file.isDirectory()){
			File [] files = file.listFiles();
			for(int i = 0; i < files.length; i ++){
				list.add(files[i].getName());
			}
		}
		return list;
	}

	/**
	 * 故障码的PUCB码
	 * @param code 故障码字节数组
	 * @param dtclen 故障码字节数
	 * @return 字符串PUBC码
	 */
	public static String getPUBCCode(byte [] code,int dtclen){
		String pcode = "P";
		switch(code[0] & 0xC0){
			case 0x00:
				pcode = "P";
				break;
			case 0x40:
				pcode = "C";
				break;
			case 0x80:
				pcode = "B";
				break;
			case 0xC0:
				pcode = "U";
				break;
		}
		pcode += byteToHexString((byte)(code[0] & 0x3F)) + byteToHexString(code[1]);
		if(dtclen == 3){
			pcode += byteToHexString(code[2]);
		}
		return pcode;
	}

	/**
	 * 获取日期
	 * @param type  "-"或""
	 * @return 返回日期
	 */
	public static String getDate(String type){
		return new SimpleDateFormat("yyyy"+type+"MM"+type+"dd",Locale.CHINA).format(new Date());
	}

	/**
	 * 获取时间 时间格式 24时制
	 * @param type  ":"或""
	 * @return 返回时间
	 */
	public static String getTime(String type){//24时制,type="",:;
		return new SimpleDateFormat("HH"+type+"mm"+type+"ss",Locale.CHINA).format(new Date());
	}

	/**
	 * 获取日期时间 时间格式 24时制
	 * @return 返回时间
	 */
	public static String getDateTime(){
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA).format(new Date());
	}

	/**
	 * 获取日期时间毫秒  时间格式 24时制
	 * @return 返回时间
	 */
	public static String getTimeMs(){
		Date time=new Date();
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA).format(time)+"."+String.valueOf(time.getTime()%1000+1000).substring(1);
	}

	/**
	 * 线程休眠
	 * @param time 休眠时间
	 */
	public static void sleep(int time){
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置存储值
	 * @param type 存储键
	 * @param value 存储值
	 */
	public static void setSharedPreference(String type, String value){
		Editor editor = share.edit();
		editor.putString(type, value);
		editor.commit();
	}

	public static int bytesCompare(byte [] A,byte [] B)
	{
		int isok = 1;
		for(int i = 0; i < A.length; i ++)
		{
			if(A[i] != B[i])
			{
				isok = 0;
				break;
			}
		}
		return isok;
	}

	/**
	 * 获取存储值
	 * @param type 存储键
	 * @param value 默认值,没有值时
	 */
	public static String getSharedPreference(String type, String... value){
		return share.getString(type, value.length > 0 ? value[0] : "0");
	}

	/**
	 * 获取5个长度的字符串的byte长度 +源字符串
	 * @param result 可包含中文的字符串
	 * @return 例如:"23中国ab" ,返回"00008+result"
	 */
	public static String getByteLenOfFive(String result){
		return String.valueOf(100000 + result.getBytes().length).substring(1,6) + result;
	}

	/**
	 * @param filename 文件路径
	 * @param datas    文件字节数组集合
	 * @param startAdd 文件每段起始地址字节数组集合
	 * @param sizes	        文件每段字节大小数组 集合
	 */
	public static void readFileFromS19(String filename,ArrayList<byte[]> datas,ArrayList<byte[]> startAdd,ArrayList<byte[]> sizes){
		BufferedReader br;
		String line="";
		int allNum=0;//已读总字节数
		long frontAdd=0;//前一行地址
		long frontSize=0;//前一行有效字节数
		long currentAdd;//当前地址
		int currentLen=0;//当前有效字节数
		int duanLen=0;//每一段总字节数
		byte[] data=new byte[5000000];
		boolean first=true;
		try {
			br=new BufferedReader(new FileReader(filename));
			while((line=br.readLine())!=null){
				if(line.length()>1){
					int type=line.charAt(1)-48;
					if(type>0&&type<4){
						currentLen=Integer.valueOf(line.substring(2,4),16)-(type+2);
						currentAdd=Long.valueOf(line.substring(4,6+type*2),16);
						if(((frontAdd+frontSize)==0&&currentAdd==0)||(frontAdd+frontSize!=currentAdd)){
							if(!first){//是否是第一次
								sizes.add(longTobytes(duanLen));
								duanLen=0;
								datas.add(data);
								allNum=0;
								data=new byte[5000000];
							}
							first=false;
							startAdd.add(longTobytes(currentAdd));
						}
						byte[]e=line.substring(6+type*2,(int)currentLen*2+6+type*2).getBytes();
						for (int m =0; m <currentLen; m++) {
							data[m+allNum]=(byte) ((charToHexInt((char)e[m*2])<<4)|charToHexInt((char) e[m*2+1]));
						}
						duanLen+=currentLen;
						frontAdd=currentAdd;
						frontSize=currentLen;
						allNum+=currentLen;
					}
				}
			}
			sizes.add(longTobytes(duanLen));//最后一段
			datas.add(data);//最后一段
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * @param filename 文件路径
	 * @param datas    文件字节数组
	 * @param startAdd 文件每段起始地址集合
	 * @param sizes	        文件每段字节大小集合
	 */
	public static void readFileFromS19(String filename,byte[] datas,ArrayList<Long> startAdd,ArrayList<Integer> sizes){
		BufferedReader br;
		String line="";
		int allNum=0;//已读总字节数
		long frontAdd=0;//前一行地址
		long frontSize=0;//前一行有效字节数
		long currentAdd;//当前地址
		int currentLen=0;//当前有效字节数
		int duanLen=0;//每一段总字节数
		boolean first=true;
		try {
			br=new BufferedReader(new FileReader(filename));
			while((line=br.readLine())!=null){
				if(line.length()>1){
					int type=line.charAt(1)-48;
					if(type>0&&type<4){
						currentLen=Integer.valueOf(line.substring(2,4),16)-(type+2);
						currentAdd=Long.valueOf(line.substring(4,6+type*2),16);
						if(((frontAdd+frontSize)==0&&currentAdd==0)||(frontAdd+frontSize!=currentAdd)){
							if(!first){//是否是第一次
								sizes.add(duanLen);
								duanLen=0;
							}
							first=false;
							startAdd.add(currentAdd);
						}
						byte[]e=line.substring(6+type*2,(int)currentLen*2+6+type*2).getBytes();
						for (int m =0; m <currentLen; m++) {
							datas[m+allNum]=(byte) ((charToHexInt((char) e[m*2])<<4)|charToHexInt((char)e[m*2+1]));
						}
						duanLen+=currentLen;
						frontAdd=currentAdd;
						frontSize=currentLen;
						allNum+=currentLen;
					}
				}
			}
			sizes.add(duanLen);//最后一段
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * @param filename 文件路径
	 * @param datas    文件字节数组集合
	 * @param startAdd 文件每段起始地址字节数组集合
	 * @param sizes	        文件每段字节大小数组 集合
	 */
	public static void readFileFromHex(String filename,ArrayList<byte[]> datas,ArrayList<byte[]> startAdds,ArrayList<byte[]> sizes){
		BufferedReader br;
		String line="";
		int allNum=0;//已读总字节数
		long frontAdd=0;//前一行地址
		long frontSize=0;//前一行有效字节数
		long start = 0;//当前地址的前两个字节
		long currentAdd = 0;//当前地址
		int currentLen=0;//当前有效字节数
		int duanLen=0;//每一段总字节数
		byte[] data=new byte[5000000];
		boolean invalied=false;//无效字节
		boolean first=true;
		try {
			br=new BufferedReader(new FileReader(filename));
			while((line=br.readLine())!=null){
				if(line.charAt(8)==52){//04表示起始地址前两个字节
					start=Long.valueOf(line.substring(9,13)+"0000",16);
					invalied=false;
				}else if(line.charAt(8)==48){//00表示有效数据
					if(invalied) continue;
					currentLen=Integer.valueOf(line.substring(1,3),16);
					currentAdd=Long.valueOf(line.substring(3,7),16);
					if(((frontAdd+frontSize)==0&&currentAdd==0)||(frontAdd+frontSize!=currentAdd)){
						if(!first){
							sizes.add(longTobytes(duanLen));//不是首段
							datas.add(data);
							duanLen=0;
							allNum=0;
							data=new byte[5000000];
						}
						first=false;
						startAdds.add(longTobytes(start+currentAdd));
					}
					byte[]e=line.substring(9,line.length()-2).getBytes();
					for (int m =0; m <currentLen; m++) {
						data[m+allNum]=(byte) ((charToHexInt((char)e[m*2])<<4)|charToHexInt((char)e[m*2+1]));
					}
					duanLen+=currentLen;
					frontAdd=currentAdd;
					frontSize=currentLen;
					allNum+=currentLen;
				}else if(line.charAt(8)== 0x32){ //扩展地址不管
					start = frontAdd+frontSize;
				}else{
					invalied=true;
				}
			}
			sizes.add(longTobytes(duanLen));//最后一段
			datas.add(data);//最后一段
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	//返回总长度，Pblock[0] -- 块数，后面是每块长度
	public static int ReadHexFile(String Pfile,byte [] readbuf,int [] Pblock) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		int len = 0;
		//int v_adress = 0;
		boolean isstart = false;
		byte [] v_adr = new byte[4];
		byte [] v_buf = new byte[64];
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line == null) break;
			if(line.length() > 0)
			{
				v_adr.clone();
				len = ReadHexLine(line, v_adr,v_buf);
				//v_adress = (v_adr[0]&0xFF) * 0x1000000 + (v_adr[1]&0xFF) * 0x10000 + (v_adr[2]&0xFF) * 0x100 + (v_adr[3]&0xFF);
				if(isstart == false)
				{
					if(len == 1000) //头
					{
						isstart = true;
						//copy
						//System.arraycopy(v_adr, 0, Padr, 0, 2);
						//Padr[0] = v_adr[0];
						//Padr[1] = v_adr[1];
						readlen = 0;
					}
					else if(len == 0)
					{
						break;
					}
				}
				else if(len > 0 && len < 100)
				{
					System.arraycopy(v_buf, 0, readbuf, readlen, len);
					readlen += len;
				}
				else if(len == 1000)
				{

				}
				else
				{
					break;
				}
			}
		}
		//临时先用
		Pblock[0] = 1;
		Pblock[1] = readlen;
		return readlen;
	}

	/**
	 * @param filename 文件路径
	 * @param datas    文件字节数组
	 * @param startAdd 文件每段起始地址集合
	 * @param sizes	        文件每段字节大小集合
	 */
	public static void readFileFromHex(String filename,byte[] datas,ArrayList<Long> startAdds,ArrayList<Integer> sizes){
		BufferedReader br;
		String line="";
		int allNum=0;//已读总字节数
		long frontAdd=0;//前一行地址
		long frontSize=0;//前一行有效字节数
		long start = 0;//当前地址的前两个字节
		long currentAdd = 0;//当前地址
		int currentLen=0;//当前有效字节数
		int duanLen=0;//每一段总字节数
		boolean invalied=false;//无效字节
		boolean first=true;
		try {
			br=new BufferedReader(new FileReader(filename));
			while((line=br.readLine())!=null){
				if(line.length()<8)continue;
				if(line.charAt(8)== 0x34){//04表示起始地址前两个字节
					start=Long.valueOf(line.substring(9,13)+"0000",16);
					invalied=false;
				}else if(line.charAt(8)== 0x30){//00表示有效数据
					if(invalied) continue;
					currentLen=Integer.valueOf(line.substring(1,3),16);
					currentAdd=start+Long.valueOf(line.substring(3,7),16);
					if(((frontAdd+frontSize)==0&&currentAdd==0)||(frontAdd+frontSize!=currentAdd)){
						if(!first){
							sizes.add(duanLen);//不是首段
							duanLen=0;
						}
						first=false;
						startAdds.add(currentAdd);
					}
					byte[]e=line.substring(9,line.length()-2).getBytes();
					for (int m =0; m <currentLen; m++) {
						datas[m+allNum]=(byte) ((charToHexInt((char)e[m*2])<<4)|charToHexInt((char)e[m*2+1]));
					}
					duanLen+=currentLen;
					frontAdd=currentAdd;
					frontSize=currentLen;
					allNum+=currentLen;
				}else if(line.charAt(8)== 0x32){ //扩展地址不管
					start = frontAdd+frontSize;
				}else{
					invalied=true;
				}
			}
			sizes.add(duanLen);//最后一段
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	//获取Dictionary下面的子文件夹
	public static List<String> GetDictionarySonList(String DirName)
	{
		List<String> mylist = new ArrayList<String>();
		File mainfile = new File(DirName);
		if(mainfile == null) return mylist;
		if(mainfile.isDirectory() == false) return mylist;
		File [] files = mainfile.listFiles();
		if(files.length <= 0) return mylist;
		for(int i = 0; i < files.length; i ++)
		{
			if(files[i].isDirectory())
				mylist.add(files[i].getName());
		}
		return mylist;
	}
	public static final String msToString(int ms)
	{
		String st = Integer.toString(ms);
		if(st.length() < 2)
			st = "00" + st;
		else if(st.length() < 3)
			st = "0" + st;
		return st;
	}
	public static int GetBinFileLength(String Pfile) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		int len = 0;
		byte [] v_buf = new byte[16];
		len = fileInputStream.read(v_buf);
		while (len > 0)
		{
			//数据
			readlen += len;
			len = fileInputStream.read(v_buf);
		}
		fileInputStream.close();
		return readlen;
	}
	public static int ReadBinFile(String Pfile,byte [] readbuf) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		int len = 0;
		byte [] v_buf = new byte[16];
		len = fileInputStream.read(v_buf);
		while (len > 0)
		{
			//copy数据
			System.arraycopy(v_buf, 0, readbuf, readlen, len);
			readlen += len;
			len = fileInputStream.read(v_buf);
		}
		fileInputStream.close();
		return readlen;
	}
	public static int ReadBinFile_TsingShan(String Pfile,byte [] readbuf) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		int len = 0;
		byte [] v_buf = new byte[16];
		byte [] v_adr = new byte[4];
		len = fileInputStream.read(v_adr);
		len = fileInputStream.read(v_buf);
		while (len > 0)
		{
			//copy数据
			System.arraycopy(v_buf, 0, readbuf, readlen, len);
			readlen += len;
			len = fileInputStream.read(v_buf);
		}
		fileInputStream.close();
		return readlen;
	}
	public static int GetHexFileLength(String Pfile,byte [] Padr) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		int len = 0;
		//int v_adress = 0;
		boolean isstart = false;
		byte [] v_adr = new byte[4];
		//byte [] v_buf = new byte[64];
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line == null) break;
			if(line.length() > 0)
			{
				v_adr.clone();
				len = ReadHexLine(line, v_adr,null);
				//v_adress = (v_adr[0]&0xFF) * 0x1000000 + (v_adr[1]&0xFF) * 0x10000 + (v_adr[2]&0xFF) * 0x100 + (v_adr[3]&0xFF);
				if(isstart == false)
				{
					if(len == 1000) //头
					{
						isstart = true;
						//copy
						//System.arraycopy(v_adr, 0, Padr, 0, 2);
						Padr[0] = 0x01;
						Padr[1] = v_adr[0];
						Padr[2] = v_adr[1];
						readlen = 0;
					}
					else if(len == 0)
					{
						break;
					}
				}
				else if(len > 0 && len < 100)
				{
					if(readlen == 0)
						System.arraycopy(v_adr, 0, Padr, 3, 2);
					readlen += len;
				}
				else if(len == 1000)
				{

				}
				else
				{
					break;
				}
			}
		}
		return readlen;
	}
	//返回 0--结束,1000-头地址,1- 100实际数据长度
	static int ReadHexLine(String Pline,byte [] Padr,byte [] Pdata)
	{
		int error = 0;
		int len = 0;
		String head = Pline.substring(0,3);
		Pline = Pline.substring(3);
		byte [] v_buf = new byte[64];
		if(head.equals(":02")) //头
		{
			len = Commonfunc.StringToBytes(Pline, v_buf, v_buf.length);
			if(len < 4) return 0;
			System.arraycopy(v_buf, 3, Padr, 0,2);
			error = 1000;
		}
		else if(head.equals(":00")) //结束
		{
			error = 0;
		}
		else
		{
			int buflen = HexStringtoInt(head.substring(1));
			len = Commonfunc.StringToBytes(Pline, v_buf, v_buf.length);
			if(len < 4) return 0;
			if((buflen + 4) == len) //ok
			{
				error = buflen;
				//copy
				System.arraycopy(v_buf, 0, Padr, 0,2);  //address
				if(Pdata != null)
					System.arraycopy(v_buf, 3, Pdata, 0,buflen);	//data
			}
			else
				error = 0;
		}
		return error;
	}
	public static int ReadRsaFile(String Pfile,byte [] readbuf)  throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		int adr = 0;
		long v_buf_size = readbuf.length;
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line == null) break;
			if(line.length() > 0)
			{
				//解析RSA字符串
				adr = line.indexOf("0x");
				String v_ch = "";
				while (adr >= 0)
				{
					v_ch = line.substring(adr + 2,adr + 4);
					if(v_ch != null && v_ch.length() == 2) {
						readbuf[readlen++] = (byte) hexStringtoInt(v_ch);
						//跳下一个
						if(readlen >= v_buf_size) break;
						line = line.substring(adr + 4);
						adr = line.indexOf("0x");
					}
					else
						break;
				}

			}
		}
		return readlen;
	}
	public static int HexStringtoInt(String hexstr)
	{
		int x=0,iRet = 0;
		if(hexstr == null)
			return iRet;
		int length = hexstr.length();
		for(int i = 0; i < length; i ++)
		{
			char c = hexstr.charAt(i);
			//对'0'->0，'a'->10
			if(c>='a'&&c<='f'){
				x=c-'a'+10;
			}else if(c>='A'&&c<='F'){
				x=c-'A'+10;
			}else if(c>='0'&&c<='9'){
				x=c-'0';
			}
			iRet=(iRet<<4)| x;//n=n*4+x,移位拼接
		}
		return iRet;
	}
	public static int StringToBytes(String str,byte[] buf,int cmdlen)
	{
//		if(Common.Debug) Log.i(TAG,"Src:" + str);
		int len = 0;
		int strlen = str.length();
		for(int i = 0; i < cmdlen; i ++)
		{
			String data = "";
			if(strlen >= (i* 2 + 2))
				data = str.substring(i * 2, i * 2 + 2);
			else
				break;
			//if(Common.Debug) Log.i(TAG,"data:"+ data);
			buf[i] = (byte) HexStringtoInt(data);
			len ++;
		}
		//if(Common.Debug) Log.i(TAG,"Obj:"+ bytesToHexString(buf, 0,cmdlen));
		return len;
	}
	static short [] crctab=
			{
					0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
					(short) 0x8108, (short) 0x9129, (short) 0xA14A, (short) 0xB16B, (short) 0xC18C, (short) 0xD1AD, (short) 0xE1CE, (short) 0xF1EF,
					0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
					(short) 0x9339, (short) 0x8318, (short) 0xB37B, (short) 0xA35A, (short) 0xD3BD, (short) 0xC39C, (short) 0xF3FF, (short) 0xE3DE,
					0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
					(short) 0xA56A, (short) 0xB54B, (short) 0x8528, (short) 0x9509, (short) 0xE5EE, (short) 0xF5CF, (short) 0xC5AC, (short) 0xD58D,
					0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
					(short) 0xB75B, (short) 0xA77A, (short) 0x9719, (short) 0x8738, (short) 0xF7DF, (short) 0xE7FE, (short) 0xD79D, (short) 0xC7BC,
					0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
					(short) 0xC9CC, (short) 0xD9ED, (short) 0xE98E, (short) 0xF9AF, (short) 0x8948, (short) 0x9969, (short) 0xA90A, (short) 0xB92B,
					0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
					(short) 0xDBFD, (short) 0xCBDC, (short) 0xFBBF, (short) 0xEB9E, (short) 0x9B79, (short) 0x8B58, (short) 0xBB3B, (short) 0xAB1A,
					0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
					(short) 0xEDAE, (short) 0xFD8F, (short) 0xCDEC, (short) 0xDDCD, (short) 0xAD2A, (short) 0xBD0B, (short) 0x8D68, (short) 0x9D49,
					0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
					(short) 0xFF9F, (short) 0xEFBE, (short) 0xDFDD, (short) 0xCFFC, (short) 0xBF1B, (short) 0xAF3A, (short) 0x9F59, (short) 0x8F78,
					(short) 0x9188, (short) 0x81A9, (short) 0xB1CA, (short) 0xA1EB, (short) 0xD10C, (short) 0xC12D, (short) 0xF14E, (short) 0xE16F,
					0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
					(short) 0x83B9, (short) 0x9398, (short) 0xA3FB, (short) 0xB3DA, (short) 0xC33D, (short) 0xD31C, (short) 0xE37F, (short) 0xF35E,
					0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
					(short) 0xB5EA, (short) 0xA5CB, (short) 0x95A8, (short) 0x8589, (short) 0xF56E, (short) 0xE54F, (short) 0xD52C, (short) 0xC50D,
					0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
					(short) 0xA7DB, (short) 0xB7FA, (short) 0x8799, (short) 0x97B8, (short) 0xE75F, (short) 0xF77E, (short) 0xC71D, (short) 0xD73C,
					0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
					(short) 0xD94C, (short) 0xC96D, (short) 0xF90E, (short) 0xE92F, (short) 0x99C8, (short) 0x89E9, (short) 0xB98A, (short) 0xA9AB,
					0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
					(short) 0xCB7D, (short) 0xDB5C, (short) 0xEB3F, (short) 0xFB1E, (short) 0x8BF9, (short) 0x9BD8, (short) 0xABBB, (short) 0xBB9A,
					0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
					(short) 0xFD2E, (short) 0xED0F, (short) 0xDD6C, (short) 0xCD4D, (short) 0xBDAA, (short) 0xAD8B, (short) 0x9DE8, (short) 0x8DC9,
					0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
					(short) 0xEF1F, (short) 0xFF3E, (short) 0xCF5D, (short) 0xDF7C, (short) 0xAF9B, (short) 0xBFBA, (short) 0x8FD9, (short) 0x9FF8,
					0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
			};
	public static short me1781_CalcCRC16(byte [] data,int Pstart,int Plen,short Pcrc)
	{
		short crc=(short) 0xffff; /* initial value */
		if(Pcrc != crc)
			crc = Pcrc;
		byte tmp;
		int i;
		for(i=0;i<Plen;i++) {
			tmp=(byte) ((crc>>8)^data[Pstart + i]);
			crc=(short) ((crc<<8)^crctab[tmp&0xFF]);
		}
		return crc;
	}
	//整数转ip
	public static String IntToIp(int ip)
	{
		return ( ip & 0xFF) + "." +
				((ip >> 8 ) & 0xFF) + "." +
				((ip >> 16 ) & 0xFF)  + "." +
				((ip >> 24 ) & 0xFF );
	}
	public static byte CalcChechSum(byte[] data, int start, int end) {
		byte chechsum = 0;
		if (start >= 0 && start < end && data != null && data.length > 0) {
			//int calc_len = end - start;
			for (int i = start; i < end; i++) {
				chechsum += data[i];
			}
			return (byte) chechsum;
		}
		return (byte) 0x00;
	}
	//返回读到的多段数据的总长度,Padr[0] -- 表示地址组个数,4byte一组
	public static int GetS19FileLength(String Pfile,byte [] Padr) throws IOException
	{
		int readlen = 0;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		long len = 0;
		long v_adress = 0;
		long v_blockadress = 0;
		long v_block = 0;
		long v_blocklen = 0;
		boolean isstart = false;
		byte [] v_adr = new byte[4];
		//byte [] v_buf = new byte[64];
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line == null) break;
			if(line.length() > 0)
			{
				v_adr.clone();
				len = ReadS19Line(line, v_adr,null);
				v_adress = (v_adr[0]&0xFF) * 0x1000000 + (v_adr[1]&0xFF) * 0x10000 + (v_adr[2]&0xFF) * 0x100 + (v_adr[3]&0xFF);
				if(len > 0)  //开始
				{
					if(isstart == false || ((v_blockadress + v_blocklen) != v_adress)) //开启一个新的块
					{
						isstart = true;
						//拷贝起始地址
						v_blockadress = v_adress;
						v_blocklen = 0;
						System.arraycopy(v_adr, 0, Padr, (int) (1 + v_block * 4), 4);
						v_block ++;
					}
					v_blocklen += len;
					readlen += len;
				}
				else if(len == -1) //开始
				{

				}
				else
				{
					break;
				}

			}
		}
		if(v_block < 255) //正常
			Padr[0] = (byte) v_block;
		else
			readlen = 0; //异常
		return readlen;
	}
	//返回总长度，Pblock[0] -- 块数，后面是每块长度
	public static int ReadS19File(String Pfile,byte [] readbuf,int Pbufadr,int [] Pblock) throws IOException
	{
		int readlen = Pbufadr;
		FileInputStream fileInputStream = new FileInputStream(Pfile);
		InputStreamReader inputreader = new InputStreamReader(fileInputStream);
		BufferedReader buffreader = new BufferedReader(inputreader);
		String line = "";
		long len = 0;
		long v_adress = 0;
		long v_blockadress = 0;
		long v_block = 0;
		long v_blocklen = 0;
		long v_buf_size = readbuf.length;
		byte [] v_adr = new byte[4];
		byte [] v_buf = new byte[64];
		while ((line = buffreader.readLine()) != null)
		{
			//解析数据
			if(line == null) break;
			if(readlen >= readbuf.length) break;
			if(line.length() > 0)
			{
				v_adr.clone();
				len = ReadS19Line(line, v_adr, v_buf);
				v_adress = (v_adr[0]&0xFF) * 0x1000000 + (v_adr[1]&0xFF) * 0x10000 + (v_adr[2]&0xFF) * 0x100 + (v_adr[3]&0xFF);
				if(len > 0)  //开始
				{
					if(((v_blockadress + v_blocklen) != v_adress) || (v_adress == 0)) //开启一个新的块
					{
						//拷贝起始地址
						//System.arraycopy(v_adr, 0, Padr, 1 + v_block * 4, 4);
						if(v_blocklen > 0)
							Pblock[(int) v_block] = (int) v_blocklen;
						v_blocklen = 0;
						v_blockadress = v_adress;
						v_block ++;
					}
					if(v_buf_size < (readlen + len))
						break;
					System.arraycopy(v_buf, 0, readbuf, readlen, (int) len);
					v_blocklen += len;
					readlen += len;
				}
				else if(len == -1) //开始
				{

				}
				else
				{
					break;
				}
			}
		}
		//记录最后一块
		if(v_blocklen > 0)
			Pblock[(int) v_block] = (int) v_blocklen;
		//记录块数
		Pblock[0] = (int) v_block;
		return readlen;
	}
	static int ReadS19Line(String Pline,byte [] Padr, byte [] Pbuf)
	{
		int len = 0;
		String head = Pline.substring(0,2);
		Pline = Pline.substring(2);
		byte [] v_buf = new byte[Pline.length() / 2];
		if(head.equals("S3") || head.equals("S2") || head.equals("S1"))
		{
			len = Commonfunc.StringToBytes(Pline, v_buf, v_buf.length);
			if(len < 5 || (len != ((v_buf[0]&0xFF) + 1))) return 0;
			//addr
			int adrlen = (head.getBytes()[1]&0xFF) - 0x30 + 1;
			System.arraycopy(v_buf, 1, Padr, 4 - adrlen, adrlen);
			len = len - adrlen - 2;
			if(Pbuf != null)
				System.arraycopy(v_buf, adrlen + 1, Pbuf, 0, len);
		}
		else if(head.equals("S0")) //开始获取地址高字节
		{
			len = -1;
		}
		else if(head.equals("S7") || head.equals("S8")) //结束
		{
			len = -2;
		}
		return len;
	}
}
